import requests
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.webdriver.common.by import By
from captcha_recognizer import CaptchaRecognizer
import base64
from PIL import Image
import io
import configparser
import os
import json
from logger_config import auto_login_logger
from selenium.common.exceptions import TimeoutException, NoSuchElementException


class AutoLogin:
    def __init__(self, driver, title, auto_submit=True):
        self.driver = driver
        self.title = title
        self.auto_submit = auto_submit

        auto_login_logger.info(f"开始自动登录... 标题: {title}, 自动提交: {auto_submit}")

        # 初始化配置
        self.config = configparser.ConfigParser()
        config_path = 'config.ini'
        auto_login_logger.debug(f"配置文件路径: {os.path.abspath(config_path)}")

        # 加载web元素配置
        self.web_elements = self.load_web_elements()
        # 初始化验证码识别器，避免每次调用 strategies 都重新初始化
        auto_login_logger.debug("初始化验证码识别器")
        try:
            self.recognizer = CaptchaRecognizer()
        except Exception as e:
            auto_login_logger.error(f"初始化验证码识别器失败: {e}")
            self.recognizer = None
            return
        
        # 确保autologin配置段存在
        if not os.path.exists(config_path):
            auto_login_logger.warning(f"配置文件 {config_path} 不存在，创建默认配置")
            self.config['autologin'] = {}
        else:
            self.config.read(config_path , 'utf-8')
            if 'autologin' not in self.config:
                self.config['autologin'] = {}

        # 如果配置段为空或不存在，创建默认配置
        if not self.config['autologin']:
            self.create_default_config(config_path)
        else:
            self.config.read(config_path,  'utf-8')

    def load_web_elements(self):
        """加载web元素配置"""
        web_elements_path = 'web_element.json'
        try:
            if os.path.exists(web_elements_path):
                with open(web_elements_path, 'r', encoding='utf-8') as f:
                    elements = json.load(f)
                auto_login_logger.info("成功加载web元素配置")
                # 确保某些字段是列表类型，即使在JSON中它们是空字符串
                for key in ['captcha_element_ids', 'possible_user_ids', 'possible_user_xpaths',
                            'possible_pwd_ids', 'possible_pwd_xpaths', 'possible_captcha_ids',
                            'possible_captcha_input_xpaths', 'submit_button_ids', 'submit_button_xpaths']:
                    if key in elements and isinstance(elements[key], str):
                        if elements[key].strip() == '': # 如果是空字符串，转换为[]
                            elements[key] = []
                        else: # 如果是非空字符串，尝试按逗号分割
                            elements[key] = [item.strip() for item in elements[key].split(',') if item.strip()]
                    elif key in elements and not isinstance(elements[key], list): # 如果不是字符串也不是列表，强制转换为空列表
                        elements[key] = []
                return elements
            else:
                auto_login_logger.warning("web_element.json文件不存在，使用默认配置并创建文件")
                default_elements = self.get_default_web_elements()
                # 创建web_element.json文件
                with open(web_elements_path, 'w', encoding='utf-8') as f:
                    json.dump(default_elements, f, indent=4, ensure_ascii=False)
                return default_elements
        except Exception as e:
            auto_login_logger.error(f"加载web元素配置失败: {e}")
            return self.get_default_web_elements()

    def get_default_web_elements(self):
        """获取默认web元素配置，返回与web_element.json一致的格式（字段为list）"""
        return {
            'captcha_element_ids': [],
            'captcha_element_xpaths': [
                "//*[@id='rc-tabs-0-panel-pwd']/div/form/div[3]/div[2]/img",
                "//*[@id='sign-box']/form[1]/div[3]/div/div/img",
                "//*[@id='rc-tabs-1-panel-pwd']/div/form/div[3]/div[2]/img",
                "//*[@id='js_vc_button']"
            ],
            'possible_user_ids': [
                "pwd_username",
                "username",
                "user_name",
                "login_username",
                "js_login_name"
            ],
            'possible_user_xpaths': [
                "//*[@id='_login']/form[1]/table/tbody/tr[2]/td[2]/div/input",
                "//*[@id='pwd_username']",
                "//*[@id='username']"
            ],
            'possible_pwd_ids': [
                "pwd_pwd",
                "password",
                "pass_word",
                "login_password",
                "pwd_pwd",
                "js_inputpass",
                "js_select_logintype"
            ],
            'possible_pwd_xpaths': [
                "//*[@id='_login']/form[1]/table/tbody/tr[3]/td[2]/div/input",
                "//*[@id='pwd_pwd']",
                "//*[@id='tUserLock']"
            ],
            'possible_captcha_ids': [
                "captcha",
                "pwd_captcha",
                "js_verifycode_dom"
            ],
            'possible_captcha_input_xpaths': [],
            'submit_button_ids': [],
            'submit_button_xpaths': [
                "//*[@id='sign-box']/form[1]/div[4]/button",
                "//*[@id='rc-tabs-0-panel-pwd']/div/form/button",
                "//*[@id='js_login']",
                "//*[@id='login']"
            ]
        }

    def create_default_config(self, config_path):
        """创建默认配置文件"""
        # 确保autologin配置段存在
        if 'autologin' not in self.config:
            self.config['autologin'] = {}

        # 只添加不存在的配置项
        defaults = {
            'auto_submit': 'True'
        }

        # 只添加不存在的配置项
        for key, value in defaults.items():
            if key not in self.config['autologin']:
                self.config['autologin'][key] = value

        # 保存配置
        with open(config_path, 'w', encoding='utf-8') as f:
            self.config.write(f)
        auto_login_logger.info("创建默认配置文件完成")

    def strategies(self, username, password, captcha=None):
        try:
            auto_login_logger.info(f"开始登录策略，用户名: {username}")

            # --- 验证码元素定位与识别 ---
            captcha_element_locators = self.web_elements.get('captcha_element_ids', []) + \
                                       self.web_elements.get('captcha_element_xpaths', [])
            captcha_text = ""
            captcha_element = None

            try:
                if captcha_element_locators:
                    # 尝试通过ID定位
                    found_by_id = False
                    for cid in self.web_elements.get('captcha_element_ids', []):
                        try:
                            captcha_element = self.driver.find_element(By.ID, cid)
                            auto_login_logger.debug(f"通过ID找到验证码元素: {cid}")
                            found_by_id = True
                            break
                        except NoSuchElementException:
                            auto_login_logger.debug(f"通过ID {cid} 未找到验证码元素。")

                    # 如果ID未找到，尝试通过XPath定位
                    if not found_by_id:
                        for cxpath in self.web_elements.get('captcha_element_xpaths', []):
                            try:
                                captcha_element = self.driver.find_element(By.XPATH, cxpath)
                                auto_login_logger.debug(f"通过XPath找到验证码元素: {cxpath}")
                                break
                            except NoSuchElementException:
                                auto_login_logger.debug(f"通过XPath {cxpath} 未找到验证码元素。")

                    if captcha_element:
                        location = captcha_element.location
                        size = captcha_element.size
                        screenshot = self.driver.get_screenshot_as_png()
                        img = Image.open(io.BytesIO(screenshot))

                        # 裁剪验证码区域
                        left = location['x']
                        top = location['y']
                        right = left + size['width']
                        bottom = top + size['height']
                        img = img.crop((left, top, right, bottom))

                        # 转换为字节数据
                        img_byte_arr = io.BytesIO()
                        img.save(img_byte_arr, format='PNG')
                        img_data = img_byte_arr.getvalue()

                        # 识别验证码
                        captcha_text = self.recognizer.recognize(img_data)
                        auto_login_logger.info(f"验证码识别结果: {captcha_text}")
                    else:
                        auto_login_logger.warning("未能找到验证码图片元素，跳过验证码识别。")

                else:
                    auto_login_logger.info("未配置验证码元素定位器，跳过验证码识别。")

            except Exception as e:
                auto_login_logger.error(f"处理验证码识别时发生错误: {e}")
                captcha_text = ""

            # --- 用户名输入框定位与输入 ---
            user_input = None
            user_locators = self.web_elements.get('possible_user_ids', []) + \
                            self.web_elements.get('possible_user_xpaths', [])
            for uloc in user_locators:
                try:
                    if uloc.startswith('//') or uloc.startswith('('):
                        user_input = self.driver.find_element(By.XPATH, uloc)
                    else:
                        user_input = self.driver.find_element(By.ID, uloc)
                    user_input.clear()
                    user_input.send_keys(username)
                    auto_login_logger.debug(f"成功输入用户名，使用定位器: {uloc}")
                    break
                except NoSuchElementException:
                    auto_login_logger.debug(f"通过定位器 {uloc} 未找到用户名输入框。")
                    continue
            if not user_input:
                raise NoSuchElementException("无法定位用户名输入框，请检查 web_element.json 配置。")

            # --- 密码输入框定位与输入 ---
            password_input = None
            pwd_locators = self.web_elements.get('possible_pwd_ids', []) + \
                           self.web_elements.get('possible_pwd_xpaths', [])
            for ploc in pwd_locators:
                try:
                    if ploc.startswith('//') or ploc.startswith('('):
                        password_input = self.driver.find_element(By.XPATH, ploc)
                    else:
                        password_input = self.driver.find_element(By.ID, ploc)
                    password_input.clear()
                    password_input.send_keys(password)
                    auto_login_logger.debug(f"成功输入密码，使用定位器: {ploc}")
                    break
                except NoSuchElementException:
                    auto_login_logger.debug(f"通过定位器 {ploc} 未找到密码输入框。")
                    continue
            if not password_input:
                raise NoSuchElementException("无法定位密码输入框，请检查 web_element.json 配置。")

            # --- 验证码输入框定位与输入 (如果识别到验证码) ---
            if captcha_text:
                captcha_input = None
                captcha_input_locators = self.web_elements.get('possible_captcha_ids', []) + \
                                         self.web_elements.get('possible_captcha_input_xpaths', [])
                for cil in captcha_input_locators:
                    try:
                        if cil.startswith('//') or cil.startswith('('):
                            captcha_input = self.driver.find_element(By.XPATH, cil)
                        else:
                            captcha_input = self.driver.find_element(By.ID, cil)
                        captcha_input.clear()
                        captcha_input.send_keys(captcha_text)
                        auto_login_logger.debug(f"成功输入验证码，使用定位器: {cil}")
                        break
                    except NoSuchElementException:
                        auto_login_logger.debug(f"通过定位器 {cil} 未找到验证码输入框。")
                        continue
                if not captcha_input:
                    auto_login_logger.warning("未能找到验证码输入框，即使已识别到验证码。")

            # --- 提交按钮定位与点击 ---
            if self.auto_submit:
                auto_login_logger.info("开始自动提交登录")
                submit_button = None
                submit_locators = self.web_elements.get('submit_button_ids', []) + \
                                  self.web_elements.get('submit_button_xpaths', [])
                for sloc in submit_locators:
                    try:
                        if sloc.startswith('//') or sloc.startswith('('):
                            submit_button = self.driver.find_element(By.XPATH, sloc)
                        else:
                            submit_button = self.driver.find_element(By.ID, sloc)
                        submit_button.click()
                        auto_login_logger.info(f"成功点击登录按钮，使用定位器: {sloc}")
                        break
                    except NoSuchElementException:
                        auto_login_logger.debug(f"通过定位器 {sloc} 未找到登录按钮。")
                        continue
                if not submit_button:
                    raise NoSuchElementException("无法定位登录按钮，请检查 web_element.json 配置。")
            else:
                auto_login_logger.info("自动提交已禁用，跳过点击登录按钮")

        except NoSuchElementException as e:
            auto_login_logger.error(f"登录失败，关键元素未找到: {e}")
            raise # Re-raise to propagate to main_window.py for UI feedback
        except Exception as e:
            auto_login_logger.error(f"登录过程中发生未知错误: {e}")
            raise # Re-raise for UI feedback.
    def login(self, username, password):
        try:
            auto_login_logger.info(f"开始登录流程，用户名: {username}")
            # 引入 WebDriverWait 增加等待机制，等待页面加载完成或特定元素出现
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.TAG_NAME, "body"))
            )
            self.strategies(username, password)
            auto_login_logger.info("登录流程完成")
        except TimeoutException:
            auto_login_logger.error("页面加载超时，无法执行登录操作。")
            self.driver.quit() # 尝试关闭浏览器以避免僵尸进程
        except Exception as e:
            auto_login_logger.error(f"登录失败: {e}")
        # self.driver.execute_script(f"document.title='{self.title}'")